#ifndef SYNC_PROTECT_MODULE
#define SYNC_PROTECT_MODULE

#include <Windows.h>
#include <stdio.h>
#include "Hw3Types.h"
#include "Hw3TypesExtended.h"
#include "GlobalVariables.h"

/*oOoOoOoOoOoOoOoOoOoOoOoOooOoOoOoOoOoO*/
//		Sync And Protection Module
/*oOoOoOoOoOoOoOoOoOoOoOoOooOoOoOoOoOoO*/
// This module is in charge of the synchronization and protection used in the program, allowing  
// the threads to create threads and events. Also it is in charge of the "safe" exit from the program. 

// IsProgramTerminated
// ===================
// This function checks the status of the hTerminateProgram event and returns TRUE if it is set, or FALSE if 
// it is not set. This function is used in different places in the code to make sure that once an error occured or
// a duplicate face was found, the program will exit immidiatly and in an organized fashion.
BOOL IsProgramTerminated();

// CreateReadEvents
// ================
// This function create an array of events, each representing a line in the picture. Each such event is set only when 
// the corresponding line has finished loading. This allows us to synchronize the searching threads and to allow them
// to start searching only when enough lines have been loaded.
// The function uses information from the global ImageReaderAndProperties variable, so it must be set prior to using 
// this function. 
// Output: Success - TRUE. Failure - FALSE.
BOOL CreateReadEvents();

// CloseReadEvents
// ================
// This function closes the handles to the events in the hReadEvents array. 
// This function should be called before ending the program. 
void CloseReadEvents();



// CreateThreadSimple
// ==================
// This function creates a thread by calling Win32 Api's CreateThread()
// function, and setting some of the parameters to default value. 
// Inputs:
//		- StartAddress - a pointer to the function that will be run by the thread.
//		- ParameterPtr - a pointer to the parameter that will be supplied to the 
//			               function run by the thread.
//		- ThreadIdPtr - return argument: a pointer to a DWORD variable into which 
//			              the function will write the created thread's ID.
// Output: On success, a handle to the created thread. On Failure - NULL.
HANDLE CreateThreadSimple(  LPTHREAD_START_ROUTINE StartAddress, 
                            LPVOID ParameterPtr, 
                            LPDWORD ThreadIdPtr );

// IncreaseOpenThreadsCounter and DecreaseOpenThreadsCounter
// =========================================================
// These two functions allows to increase or decrease the open threads counter. The access to the counter is protected
// with a mutex to prevent a collision between two threads trying to access it simultaneously. The open threads
// counter is used to determine when all threads have finished running and the program can begin the clean up
// procedure before exiting. For that reason, it is very important to increase the counter when a thread is created
// and decrease it when a thread has finished running. Failing to do so can cause a deadlock, or a situation where the
// program exits before all threads have finished running.
BOOL IncreaseOpenThreadsCounter();
BOOL DecreaseOpenThreadsCounter();

// PrintErrorAndTerminate
// ======================
// This function prints the relevant error to the end file (in case it hasn't been previously written) and sets the 
// hTerminateProgram event, to inform all threads that the program should end and they should start cleaning up
// and exiting.
// Inputs:
//		- A TError argument that specifies the type of error that occured.
void PrintErrorAndTerminate(TError Error);

#endif